home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / util / libs / prooflibrary10.lha / prooflibrary / examples / create / scale.c < prev    next >
C/C++ Source or Header  |  1999-01-30  |  8KB  |  370 lines

  1. #include <math.h>
  2. #include <string.h>
  3.  
  4. #include <exec/memory.h>
  5. #include <exec/types.h>
  6.  
  7. #include <clib/exec_protos.h>
  8.  
  9. #include <pragmas/exec_pragmas.h>
  10.  
  11. #include "scale.h"
  12.  
  13. /* Function protoytypes */
  14. void scale_region( struct PixelRegion *srcPR, struct PixelRegion *destPR, BOOL cubic_interpolation );
  15. double cubic( double dx, int jm1, int j, int jp1, int jp2 );
  16. void pixel_region_get_row( struct PixelRegion *srcPR, int src_row, int orig_width, UBYTE *src, int num_rows );
  17. void pixel_region_set_row( struct PixelRegion *destPR, int dest_row, int width, UBYTE *dest );
  18.  
  19. void scale_region( struct PixelRegion *srcPR, struct PixelRegion *destPR, BOOL cubic_interpolation )
  20. {
  21.     unsigned char *src_m1, *src, *src_p1, *src_p2;
  22.     unsigned char *s_m1, *s, *s_p1, *s_p2;
  23.     unsigned char *dest, *d;
  24.     double *row, *r;
  25.     int src_row, src_col;
  26.     int bytes, b;
  27.     int width, height;
  28.     int orig_width, orig_height;
  29.     double x_rat, y_rat;
  30.     double x_cum, y_cum;
  31.     double x_last, y_last;
  32.     double *x_frac, y_frac, tot_frac;
  33.     float dx, dy;
  34.     int i, j;
  35.     int frac;
  36.     int advance_dest_x, advance_dest_y;
  37.     int minus_x, plus_x, plus2_x;
  38.     ScaleType scale_type;
  39.  
  40.     orig_width = srcPR->w;
  41.     orig_height = srcPR->h;
  42.  
  43.     width = destPR->w;
  44.     height = destPR->h;
  45.  
  46.     /* Some calculations */
  47.     bytes = destPR->bytes;
  48.  
  49.     /* The data pointers */
  50.     src_m1 = AllocVec( orig_width * bytes, MEMF_PUBLIC | MEMF_CLEAR );
  51.     src = AllocVec( orig_width * bytes, MEMF_PUBLIC | MEMF_CLEAR );
  52.     src_p1 = AllocVec( orig_width * bytes, MEMF_PUBLIC | MEMF_CLEAR );
  53.     src_p2 = AllocVec( orig_width * bytes, MEMF_PUBLIC | MEMF_CLEAR );
  54.     dest = AllocVec( width * bytes, MEMF_PUBLIC | MEMF_CLEAR );
  55.  
  56.     /* Find the ratios of old x to new x and old y to new y */
  57.     x_rat = (double)orig_width / (double)width;
  58.     y_rat = (double)orig_height / (double)height;
  59.  
  60.     /* Determine the scale type */
  61.     if ( x_rat < 1.0 && y_rat < 1.0 )
  62.     {
  63.         scale_type = MagnifyX_MagnifyY;
  64.     }
  65.     else if ( x_rat < 1.0 && y_rat >= 1.0 )
  66.     {
  67.         scale_type = MagnifyX_MinifyY;
  68.     }
  69.     else if ( x_rat >= 1.0 && y_rat < 1.0 )
  70.     {
  71.         scale_type = MinifyX_MagnifyY;
  72.     }
  73.     else
  74.     {
  75.         scale_type = MinifyX_MinifyY;
  76.     }
  77.  
  78.     /* Allocate an array to help with the calculations */
  79.     row = (double *)AllocVec( sizeof( double ) * width * bytes, MEMF_PUBLIC | MEMF_CLEAR );
  80.     x_frac = (double *)AllocVec( sizeof( double ) * ( width + orig_width ), MEMF_PUBLIC | MEMF_CLEAR );
  81.  
  82.     /* Initialize the pre-calculated pixel fraction array */
  83.     src_col = 0;
  84.     x_cum = (double)src_col;
  85.     x_last = x_cum;
  86.  
  87.     for ( i = 0; i < width + orig_width; i++ )
  88.     {
  89.         if ( x_cum + x_rat <= ( src_col + 1 + EPSILON ) )
  90.         {
  91.             x_cum += x_rat;
  92.             x_frac[i] = x_cum - x_last;
  93.         }
  94.         else
  95.         {
  96.             src_col ++;
  97.             x_frac[i] = src_col - x_last;
  98.         }
  99.  
  100.         x_last += x_frac[i];
  101.     }
  102.  
  103.     /* Clear the "row" array */
  104.     memset( row, 0, sizeof( double ) * width * bytes );
  105.  
  106.     /* Counters */
  107.     src_row = 0;
  108.     y_cum = (double)src_row;
  109.     y_last = y_cum;
  110.  
  111.     /* Get the first src row */
  112.     pixel_region_get_row( srcPR, src_row, orig_width, src, 1 );
  113.  
  114.     /* Get the next two if possible */
  115.     if ( src_row < ( orig_height - 1 ) )
  116.     {
  117.         pixel_region_get_row( srcPR, ( src_row + 1 ), orig_width, src_p1, 1 );
  118.     }
  119.  
  120.     if ( ( src_row + 1 ) < ( orig_height - 1 ) )
  121.     {
  122.         pixel_region_get_row( srcPR, ( src_row + 2 ), orig_width, src_p2, 1 );
  123.     }
  124.  
  125.     /* Scale the selected region */
  126.     i = height;
  127.  
  128.     while ( i )
  129.     {
  130.         src_col = 0;
  131.         x_cum = (double)src_col;
  132.  
  133.         /* Determine the fraction of the src pixel we are using for y */
  134.         if ( y_cum + y_rat <= ( src_row + 1 + EPSILON ) )
  135.         {
  136.             y_cum += y_rat;
  137.             dy = y_cum - src_row;
  138.             y_frac = y_cum - y_last;
  139.  
  140.             advance_dest_y = TRUE;
  141.         }
  142.         else
  143.         {
  144.             y_frac = ( src_row + 1 ) - y_last;
  145.             dy = 1.0;
  146.  
  147.             advance_dest_y = FALSE;
  148.         }
  149.  
  150.         y_last += y_frac;
  151.  
  152.         s = src;
  153.         s_m1 = ( src_row > 0 ) ? src_m1 : src;
  154.         s_p1 = ( src_row < ( orig_height - 1 ) ) ? src_p1 : src;
  155.         s_p2 = ( ( src_row + 1 ) < ( orig_height - 1 ) ) ? src_p2 : s_p1;
  156.  
  157.         r = row;
  158.  
  159.         frac = 0;
  160.         j = width;
  161.  
  162.         while ( j )
  163.         {
  164.             if ( x_cum + x_rat <= ( src_col + 1 + EPSILON ) )
  165.             {
  166.                 x_cum += x_rat;
  167.                 dx = x_cum - src_col;
  168.  
  169.                 advance_dest_x = TRUE;
  170.             }
  171.             else
  172.             {
  173.                 dx = 1.0;
  174.  
  175.                 advance_dest_x = FALSE;
  176.             }
  177.  
  178.             tot_frac = x_frac[ frac++ ] * y_frac;
  179.  
  180.             minus_x = ( src_col > 0 ) ? -bytes : 0;
  181.             plus_x = ( src_col < ( orig_width - 1 ) ) ? bytes : 0;
  182.             plus2_x = ( ( src_col + 1 ) < ( orig_width - 1 ) ) ? bytes * 2 : plus_x;
  183.  
  184.             if ( cubic_interpolation )
  185.             {
  186.                 switch ( scale_type )
  187.                 {
  188.                     case MagnifyX_MagnifyY:
  189.                         for ( b = 0; b < bytes; b++ )
  190.                         {
  191.                             r[b] += cubic( dy, (int)cubic( dx, s_m1[ b + minus_x ], s_m1[b], s_m1[ b + plus_x ], s_m1[ b + plus2_x ] ),
  192.                                 (int)cubic( dx, s[ b + minus_x ], s[b],    s[ b + plus_x ], s[ b + plus2_x ] ),
  193.                                 (int)cubic( dx, s_p1[ b + minus_x ], s_p1[b], s_p1[ b + plus_x ], s_p1[ b + plus2_x ] ),
  194.                                 (int)cubic( dx, s_p2[ b + minus_x ], s_p2[b], s_p2[ b + plus_x ], s_p2[ b + plus2_x ] ) ) * tot_frac;
  195.                         }
  196.                     break;
  197.  
  198.                     case MagnifyX_MinifyY:
  199.                         for ( b = 0; b < bytes; b++ )
  200.                         {
  201.                             r[b] += cubic( dx, s[ b + minus_x ], s[b], s[ b + plus_x ], s[ b + plus2_x ] ) * tot_frac;
  202.                         }
  203.                     break;
  204.  
  205.                     case MinifyX_MagnifyY:
  206.                         for ( b = 0; b < bytes; b++ )
  207.                         {
  208.                             r[b] += cubic( dy, s_m1[b], s[b], s_p1[b], s_p2[b] ) * tot_frac;
  209.                         }
  210.                     break;
  211.  
  212.                     case MinifyX_MinifyY:
  213.                         for ( b = 0; b < bytes; b++ )
  214.                         {
  215.                             r[b] += s[b] * tot_frac;
  216.                         }
  217.                     break;
  218.                 }
  219.             }
  220.             else
  221.             {
  222.                 switch ( scale_type )
  223.                 {
  224.                     case MagnifyX_MagnifyY:
  225.                         for ( b = 0; b < bytes; b++ )
  226.                         {
  227.                             r[b] += ( ( 1 - dy ) * ( ( 1 - dx ) * s[b] + dx * s[ b + plus_x ] ) +
  228.                             dy  * ( ( 1 - dx ) * s_p1[b] + dx * s_p1[ b + plus_x ] ) ) * tot_frac;
  229.                         }
  230.                     break;
  231.  
  232.                     case MagnifyX_MinifyY:
  233.                         for ( b = 0; b < bytes; b++ )
  234.                         {
  235.                             r[b] += ( s[b] * ( 1 - dx ) + s[ b + plus_x ] * dx ) * tot_frac;
  236.                         }
  237.                     break;
  238.  
  239.                     case MinifyX_MagnifyY:
  240.                         for ( b = 0; b < bytes; b++ )
  241.                         {
  242.                             r[b] += ( s[b] * ( 1 - dy ) + s_p1[b] * dy ) * tot_frac;
  243.                         }
  244.                     break;
  245.  
  246.                     case MinifyX_MinifyY:
  247.                         for ( b = 0; b < bytes; b++ )
  248.                         {
  249.                             r[b] += s[b] * tot_frac;
  250.                         }
  251.                     break;
  252.                 }
  253.             }
  254.  
  255.             if ( advance_dest_x )
  256.             {
  257.                 r += bytes;
  258.                 j--;
  259.             }
  260.             else
  261.             {
  262.                 s_m1 += bytes;
  263.                 s += bytes;
  264.                 s_p1 += bytes;
  265.                 s_p2 += bytes;
  266.                 src_col++;
  267.             }
  268.         }
  269.  
  270.         if ( advance_dest_y )
  271.         {
  272.             tot_frac = 1.0 / ( x_rat * y_rat );
  273.  
  274.             /* Copy "row" to "dest" */
  275.             d = dest;
  276.             r = row;
  277.             j = width;
  278.  
  279.             while ( j-- )
  280.             {
  281.                 b = bytes;
  282.  
  283.                 while (b--)
  284.                 {
  285.                     *d++ = (unsigned char)( *r++ * tot_frac );
  286.                 }
  287.             }
  288.  
  289.             /* Set the pixel region span */
  290.             pixel_region_set_row( destPR, ( height - i ), width, dest );
  291.  
  292.             /* Clear the "row" array */
  293.             memset( row, 0, sizeof( double ) * width * bytes );
  294.  
  295.             i--;
  296.         }
  297.         else
  298.         {
  299.             /* Shuffle pointers */
  300.             s = src_m1;
  301.             src_m1 = src;
  302.             src = src_p1;
  303.             src_p1 = src_p2;
  304.             src_p2 = s;
  305.             src_row++;
  306.  
  307.             if ( ( src_row + 1 ) < ( orig_height - 1 ) )
  308.             {
  309.                 pixel_region_get_row( srcPR, ( src_row + 2 ), orig_width, src_p2, 1 );
  310.             }
  311.         }
  312.     }
  313.  
  314.     /* Free up temporary arrays */
  315.   FreeVec( row );
  316.   FreeVec( x_frac );
  317.   FreeVec( src_m1 );
  318.   FreeVec( src );
  319.   FreeVec( src_p1 );
  320.   FreeVec( src_p2 );
  321.   FreeVec( dest );
  322. }
  323.  
  324. double cubic( double dx, int jm1, int j, int jp1, int jp2 )
  325. {
  326.     double dx1, dx2, dx3;
  327.     double h1, h2, h3, h4;
  328.     double result;
  329.  
  330.     /* Constraint parameter = -1 */
  331.     dx1 = fabs( dx );
  332.     dx2 = dx1 * dx1;
  333.     dx3 = dx2 * dx1;
  334.     h1 = dx3 - 2 * dx2 + 1;
  335.     result = h1 * j;
  336.  
  337.     dx1 = fabs( dx - 1.0 );
  338.     dx2 = dx1 * dx1;
  339.     dx3 = dx2 * dx1;
  340.     h2 = dx3 - 2 * dx2 + 1;
  341.     result += h2 * jp1;
  342.  
  343.     dx1 = fabs( dx - 2.0 );
  344.     dx2 = dx1 * dx1;
  345.     dx3 = dx2 * dx1;
  346.     h3 = -dx3 + 5 * dx2 - 8 * dx1 + 4;
  347.     result += h3 * jp2;
  348.  
  349.     dx1 = fabs( dx + 1.0 );
  350.     dx2 = dx1 * dx1;
  351.     dx3 = dx2 * dx1;
  352.     h4 = -dx3 + 5 * dx2 - 8 * dx1 + 4;
  353.     result += h4 * jm1;
  354.  
  355.     if ( result < 0.0 ) result = 0.0;
  356.   if ( result > 255.0 ) result = 255.0;
  357.  
  358.   return result;
  359. }
  360.  
  361. void pixel_region_get_row( struct PixelRegion *srcPR, int src_row, int orig_width, UBYTE *src, int num_rows )
  362. {
  363.     CopyMem( &srcPR->buf[ src_row * orig_width * srcPR->bytes ], src, orig_width * srcPR->bytes );
  364. }
  365.  
  366. void pixel_region_set_row( struct PixelRegion *destPR, int dest_row, int width, UBYTE *dest )
  367. {
  368.     CopyMem( dest, &destPR->buf[ dest_row * width * destPR->bytes ], width * destPR->bytes );
  369. }
  370.